package luke.ui.main;

import java.util.*;
import java.util.prefs.Preferences;
import java.io.File;

import javax.swing.*;

import java.awt.Color;

import luke.core.config.AppDataManager;
import luke.core.controller.PlayController;
import luke.core.utils.QRCodeValidator;
import luke.core.utils.AppStateManager;  // 新增：导入AppStateManager
import luke.core.utils.ThemeManager;
import luke.core.utils.LanguageManager; // 新增：导入LanguageManager
import luke.ui.components.MenuBar;
// 导入新的面板类
import luke.ui.components.FileListPanel;
import luke.ui.components.SelectedFilePanel;
import luke.ui.components.ProductionPanel;
import luke.ui.components.PlayPanel;
// 导入歌曲分析相关类
import luke.audio.metadata.SongMetadataExtractor;

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import javax.swing.filechooser.FileSystemView;

// 导入PlaybackStateManager
import luke.core.utils.PlaybackStateManager;

// 新增：导入更新检查相关类
import luke.ui.dialogs.UpdateChecker;

// 导入日志工具类
import luke.core.logging.LogUtil;

public class RunBeatsUI extends JFrame implements AppStateManager.StateListener {
    // 常量定义
    private static final String PREF_LAST_DIRECTORY = "last_directory";
    // 新增：版本文件的URL

    private Preferences prefs;// 用户首选项
    private AppDataManager appDataManager;// 应用数据管理器
    private LanguageManager languageManager;// 语言管理器

    private int width;// 窗宽度
    private int height;// 窗高度
    private JTextField directoryField;// 目录文本框
    private JButton browseButton;// 浏览按钮
    // 新增：去除抖音视频结尾音勾选框
    private JCheckBox removeDouyinEndingSoundCheckBox;// 去除抖音视频结尾音勾选框
    
    // 面板组件
    private FileListPanel fileListPanel;
    private SelectedFilePanel selectedFilePanel;
    private ProductionPanel productionPanel;
    private PlayPanel playPanel;
    private JLabel statusLabel; // 状态标签


    // 添加一个标志位，用于标识是否正在恢复已选择文件，避免在恢复过程中触发持久化
    private boolean isRestoringSelectedFiles = false;

    // 添加PlaybackStateManager引用
    private PlaybackStateManager playbackStateManager;
    // 添加AppStateManager引用
    private AppStateManager appStateManager;
    private SongMetadataExtractor songMetadataExtractor;
    private PlayController playController;
    private File[] files;
    private File[] allListFiles;


    public RunBeatsUI() {
        // 初始化语言管理器
        this.languageManager = LanguageManager.getInstance();
        
        // 初始化AppStateManager并注册为监听器
        this.appStateManager = AppStateManager.getInstance();
        appStateManager.addListener(this);

        // 1,前置验证
        validateStartup();
        // 2,初始化程序
        initCoreComponents();
        // 3,加载UI
        loadUI();
        // 4,检查更新
        checkForUpdates();
    }

    /**
     * 启动验证方法，用于在应用启动阶段执行必要的验证检查
     *
     * @return true表示启动验证通过，应用可以继续初始化；false表示验证失败，应用将退出
     */
    private boolean validateStartup() {
        if (!QRCodeValidator.validateQRCode()) {
            // 显示国际化错误对话框
            JOptionPane.showMessageDialog(this, 
                languageManager.getString("dialog.invalid.qr.code.message"), 
                languageManager.getString("dialog.invalid.qr.code.title"), 
                JOptionPane.ERROR_MESSAGE);
            System.exit(1);
            return false;
        }
        return true;
    }

    /**
     * 初始化核心组件方法，用于在应用启动阶段初始化核心组件
     */
    private void initCoreComponents() {
        // 初始化用户首选项节点，用于持久化存储应用配置
        prefs = Preferences.userNodeForPackage(RunBeatsUI.class);
        // 获取应用数据管理器单例，hosts 应用数据存储和配置
        appDataManager = AppDataManager.getInstance();
    }

    /*
     * 加载UI方法，用于在应用启动阶段加载UI界面
     */
    private void loadUI() {
        // 设置窗口大小为高比宽大一点的比例，确保在不同分辨率下显示一致
        width = 1280;
        height = 1080;
        setTitle(languageManager.getString("app.title")); // 设置窗口标题（国际化）
        setSize(width, height); // 设置窗口初始大小
        setLocationRelativeTo(null); // 将窗口居中显示在屏幕
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 点击关闭按钮时退出应用
        setIconImage(loadIcon("/ico/run_bpm.png")); // 加载并设置窗口图标
        // 初始化布局组件
        initializeLayoutComponents();
        // 创建并添加面板
        createAndAddPanels();
        // 加载上次使用的目录
        loadLastDirectory();
    }


    /**
     * 自动检查更新
     */
    private void checkForUpdates() {
        LogUtil.info("RunBeatsUI", "checkForUpdates", "开始自动检查更新...");

        // 在后台线程中执行更新检查
        new Thread(() -> {
            try {
                UpdateChecker updateChecker = new UpdateChecker(RunBeatsUI.this, false);
                updateChecker.checkForUpdates();
                LogUtil.info("RunBeatsUI", "checkForUpdates", "自动检查更新完成");
            } catch (Exception e) {
                LogUtil.error("RunBeatsUI", "checkForUpdates", "自动检查更新时发生异常: " + e.getMessage());
                e.printStackTrace();
            }
        }).start();
    }


    /**
     * 初始化面板组件
     */
    private void initializeLayoutComponents() {
        setJMenuBar(new MenuBar(this));

        // 初始化播放控制器
        playController = PlayController.getInstance();
        playController.setSharedSelectedFiles();
        // 初始化播放面板（需要在fileListPanel和selectedFilePanel之前初始化）
        playPanel = new PlayPanel();


        // 初始化文件列表面板和已选择文件面板
        fileListPanel = new FileListPanel();
        selectedFilePanel = new SelectedFilePanel();
        // 初始化生产面板，通过构造函数传入共享引用
        productionPanel = new ProductionPanel();
        // 初始化状态标签
        statusLabel = new JLabel(languageManager.getString("label.status.ready"));
        statusLabel.setForeground(new Color(27, 121, 148));
        
        // 初始化PlaybackStateManager
        playbackStateManager = PlaybackStateManager.getInstance();
    }

    /**
     * 创建并添加面板(这是最终模板禁止ai修改)
     */
    private void createAndAddPanels() {
        // 创建左边容器使用GridBagLayout布局
        JPanel leftPanel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc2 = new GridBagConstraints();// 创建一个GridBagConstraints对象
        gbc2.gridx = 0;// 设置组件的x坐标
        gbc2.gridy = 0;// 设置组件的y坐标
        gbc2.weightx = 1;// 设置组件的水平权重
        gbc2.weighty = 1;// 设置组件的垂直权重
        gbc2.fill = GridBagConstraints.BOTH;// 设置组件的填充方式
        // gbc2.insets = new java.awt.Insets(10, 10, 10, 10);// 设置组件的边距
        leftPanel.add(fileListPanel, gbc2);// 将文件列表面板添加到左边容器中

        // 创建一个右边容器使用GridBagLayout布局
        JPanel rightPanel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc3 = new GridBagConstraints();// 创建一个GridBagConstraints对象
        gbc3.gridx = 0;// 设置组件的x坐标
        gbc3.gridy = 0;// 设置组件的y坐标
        gbc3.weightx = 1;// 设置组件的水平权重
        gbc3.weighty = 0.95;// 设置组件的垂直权重（95%给已选择文件面板）
        gbc3.fill = GridBagConstraints.BOTH;// 设置组件的填充方式
        // gbc3.insets = new java.awt.Insets(10, 10, 10, 10);// 设置组件的边距
        rightPanel.add(selectedFilePanel, gbc3);// 将已选择文件面板添加到右边容器中

        gbc3.gridx = 0;// 设置组件的x坐标
        gbc3.gridy = 1;// 设置组件的y坐标
        gbc3.weightx = 1;// 设置组件的水平权重
        gbc3.weighty = 0.05;// 设置组件的垂直权重（5%给播放面板）
        gbc3.fill = GridBagConstraints.BOTH;// 设置组件的填充方式
        // gbc3.insets = new java.awt.Insets(10, 10, 10, 10);// 设置组件的边距
        rightPanel.add(playPanel, gbc3);// 将生产状态面板添加到右边容器中

        // 创建一个中间容器使用GridBagLayout布局
        JPanel centerPanel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();// 创建一个GridBagConstraints对象
        gbc.gridx = 0;// 设置组件的x坐标
        gbc.gridy = 0;// 设置组件的y坐标
        gbc.weightx = 0.5;// 设置组件的水平权重（50%给左侧面板，实现均匀分割）
        gbc.weighty = 1;// 设置组件的垂直权重
        gbc.fill = GridBagConstraints.BOTH;// 设置组件的填充方式
        // gbc.insets = new java.awt.Insets(10, 10, 10, 10);// 设置组件的边距
        centerPanel.add(leftPanel, gbc);// 将文件列表面板添加到中间容器中

        gbc.gridx = 1;// 设置组件的x坐标
        gbc.gridy = 0;// 设置组件的y坐标
        gbc.weightx = 0.5;// 设置组件的水平权重（50%给右侧面板，实现均匀分割）
        gbc.weighty = 1;// 设置组件的垂直权重
        gbc.fill = GridBagConstraints.BOTH;// 设置组件的填充方式
        // gbc.insets = new java.awt.Insets(10, 10, 10, 10);// 设置组件的边距
        centerPanel.add(rightPanel, gbc);// 将已选择文件面板添加到中间容器中

        // 创建一个顶部容器用来放置打开音频目录
        JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        topPanel.add(new JLabel(languageManager.getString("label.audio.directory")));
        directoryField = new JTextField(30);
        directoryField.setEditable(false);
        topPanel.add(directoryField);
        browseButton = new JButton(languageManager.getString("button.browse.directory"));
        browseButton.putClientProperty("JButton.buttonType", "roundRect");
        topPanel.add(browseButton);
        
        // 新增：添加去除抖音视频结尾音勾选框
        removeDouyinEndingSoundCheckBox = new JCheckBox(languageManager.getString("checkbox.remove.douyin.sound"), true); // 默认勾选
        topPanel.add(removeDouyinEndingSoundCheckBox);
        
        // 新增：添加勾选框状态变化监听器
        removeDouyinEndingSoundCheckBox.addActionListener(e -> {
            // 将状态发送给PlaybackStateManager
            if (playbackStateManager != null) {
                boolean isSelected = removeDouyinEndingSoundCheckBox.isSelected();
                LogUtil.debug("RunBeatsUI", "removeDouyinEndingSoundCheckBox", "去除抖音视频结尾音勾选框状态改变: " + isSelected);
                playbackStateManager.setRemoveDouyinEndingSound(isSelected);
            }
        });

        // 浏览目录按钮事件
        browseButton.addActionListener(e -> browseDirectory());

        Container contentPane = getContentPane();
        contentPane.setLayout(new GridBagLayout());
        GridBagConstraints agbc = new GridBagConstraints();
        agbc.gridx = 0;
        agbc.gridy = 0;
        agbc.weightx = 1;
        agbc.weighty = 0.05; // 5%给顶部面板
        agbc.fill = GridBagConstraints.BOTH;
        // agbc.insets = new java.awt.Insets(10, 10, 10, 10);
        contentPane.add(topPanel, agbc);

        agbc.gridx = 0;
        agbc.gridy = 1;
        agbc.weightx = 1;
        agbc.weighty = 0.70; // 70%给中间面板
        agbc.fill = GridBagConstraints.BOTH;
        // agbc.insets = new java.awt.Insets(10, 10, 10, 10);
        contentPane.add(centerPanel, agbc);

        agbc.gridx = 0;
        agbc.gridy = 2;
        agbc.weightx = 1;
        agbc.weighty = 0.20; // 20%给生产面板（增加权重以确保显示完整）
        agbc.fill = GridBagConstraints.BOTH;
        // agbc.insets = new java.awt.Insets(10, 10, 10, 10);
        contentPane.add(productionPanel, agbc);

        // 添加状态标签到界面底部
        agbc.gridx = 0;
        agbc.gridy = 3;
        agbc.weightx = 1;
        agbc.weighty = 0.05; // 5%给状态标签
        agbc.fill = GridBagConstraints.HORIZONTAL;
        contentPane.add(statusLabel, agbc);
    }

    /**
     * 加载图标方法，用于加载指定路径的图标文件
     *
     * @param path 图标文件路径
     * @return 加载的图标对象，如果加载失败则返回null
     */
    private Image loadIcon(String path) {
        try {
            return new ImageIcon(getClass().getResource(path)).getImage();
        } catch (Exception e) {
            System.err.println("无法加载图标: " + e.getMessage());
            return null;
        }
    }

    /**
     * 加载上次使用的目录
     */
    private void loadLastDirectory() {
        String lastDirectory = prefs.get(PREF_LAST_DIRECTORY, "");
        if (!lastDirectory.isEmpty()) {
            directoryField.setText(lastDirectory);
            File dir = new File(lastDirectory);
            if (dir.exists() && dir.isDirectory()) {
                // 保存目录到状态（新增这一行）
                appStateManager.setAudioDirectory(lastDirectory);
                loadAudioFiles(dir);
            }
        }
    }

    /**
     * 浏览目录方法
     */
    private void browseDirectory() {
        // 创建文件选择器实例
        JFileChooser fileChooser = new JFileChooser();
        // 设置只允许选择目录
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        // 禁用"所有文件"过滤器
        fileChooser.setAcceptAllFileFilterUsed(false);
        // 设置上次使用的目录
        String lastDirectory = prefs.get(PREF_LAST_DIRECTORY, "");
        if (!lastDirectory.isEmpty()) {
            // 使用上次保存的目录作为当前目录
            fileChooser.setCurrentDirectory(new File(lastDirectory));

        } else {
            // 如果没有保存的目录，使用系统默认的主目录
            fileChooser.setCurrentDirectory(FileSystemView.getFileSystemView().getHomeDirectory());
        }
        // 显示打开对话框并获取用户选择结果
        int returnValue = fileChooser.showOpenDialog(this);
        // 检查用户是否确认选择
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            // 获取用户选择的目录
            File selectedDirectory = fileChooser.getSelectedFile();
            // 更新目录输入框的文本
            directoryField.setText(selectedDirectory.getAbsolutePath());
            // 保存目录到偏好设置
            prefs.put(PREF_LAST_DIRECTORY, selectedDirectory.getAbsolutePath());
            // 保存目录到状态
            appStateManager.setAudioDirectory(selectedDirectory.getAbsolutePath());
            // 加载目录中的音频文件
            loadAudioFiles(selectedDirectory);
        }
    }

    /**
     * 加载音频文件 - 使用SwingWorker实时加载并显示
     */
    private void loadAudioFiles(File directory) {
        if (directory.exists() && directory.isDirectory()) {
            // 清空文件列表面板
            fileListPanel.clearFiles();

            // 获取目录中的所有音频文件
            allListFiles = directory.listFiles((dir, name) -> {
                String lowerName = name.toLowerCase();
                return lowerName.endsWith(".mp3") || lowerName.endsWith(".wav") ||
                        lowerName.endsWith(".flac") || lowerName.endsWith(".aac") ||
                        lowerName.endsWith(".ogg") || lowerName.endsWith(".mp4") ||
                        lowerName.endsWith(".m4a") || lowerName.endsWith(".wma") ||
                        lowerName.endsWith(".amr") || lowerName.endsWith(".ape") ||
                        lowerName.endsWith(".alac") || lowerName.endsWith(".ac3") ||
                        lowerName.endsWith(".mov") || lowerName.endsWith(".avi") ||
                        lowerName.endsWith(".wmv") || lowerName.endsWith(".mkv") ||
                        lowerName.endsWith(".mpeg");
            });

            if (allListFiles != null && allListFiles.length > 0) {
                // 更新AppStateManager中的所有文件列表
                appStateManager.setAllListFiles(Arrays.asList(allListFiles));
                restoreSelectedFiles();//恢复选择

                // 按文件名排序
                Arrays.sort(allListFiles, Comparator.comparing(File::getName));

                // 如果文件数量超过阈值，显示警告
                if (allListFiles.length > 1000) {
                    statusLabel.setText(languageManager.getString("label.status.loading.files").replace("{0}", String.valueOf(allListFiles.length)));
                    statusLabel.setForeground(Color.ORANGE);
                }

                // 使用SwingWorker在后台线程中加载文件
                SwingWorker<Void, File> worker = new SwingWorker<Void, File>() {
                    @Override
                    protected Void doInBackground() throws Exception {
                        // 发布文件到EDT进行UI更新
                        for (File file : allListFiles) {
                            publish(file);
                        }
                        return null;
                    }

                    @Override
                    protected void process(List<File> chunks) {
                        // 在EDT中更新UI
                        for (File file : chunks) {
                            fileListPanel.addFile(file);
                        }
                    }

                    @Override
                    protected void done() {
                        try {
                            get(); // 检查是否有异常
                            statusLabel.setText(languageManager.getString("label.status.load.complete").replace("{0}", String.valueOf(allListFiles.length)));
                            statusLabel.setForeground(new Color(27, 121, 148));
                        } catch (Exception e) {
                            statusLabel.setText(languageManager.getString("label.status.load.error").replace("{0}", e.getMessage()));
                            statusLabel.setForeground(Color.RED);
                            e.printStackTrace();
                        }
                    }
                };

                worker.execute();
            } else {
                statusLabel.setText(languageManager.getString("label.status.no.audio.files"));
                statusLabel.setForeground(Color.ORANGE);
            }
        }
    }


    @Override
    public void onSelectedFilesChanged() {
        // 当已选择文件列表改变时，保存当前选择
        saveSelectedFiles();
    }


    /**
     * 保存已选择的文件列表
     */
    private void saveSelectedFiles() {
        // 实现保存已选择文件列表的逻辑
        // 这里可以将selectedFiles保存到持久化存储中
        appDataManager.saveSelectedFiles(appStateManager.getSharedSelectedFiles(), directoryField.getText());
    }

    /**
     * 恢复已选择的文件列表
     */
    private void restoreSelectedFiles() {
        // 实现恢复已选择文件列表的逻辑
        List<File> selectedFiles = appDataManager.loadSelectedFiles(directoryField.getText(), Arrays.asList(allListFiles));
        // 这里可以从持久化存储中恢复selectedFiles
        appStateManager.setSharedSelectedFiles(selectedFiles);
    }

    /**
     * 切换播放状态
     */

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            try {
                // 设置暗灰色主题
                ThemeManager.setupDarkGrayTheme();

                // 创建并显示窗口
                RunBeatsUI frame = new RunBeatsUI();

                // 应用主题设置
                ThemeManager.applyTheme();

                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

}